/*
 * Copyright (C) 2022-2024 Huawei Device Co., Ltd.
 * Licensed under the MIT License, (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://opensource.org/licenses/MIT
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { SubscriptionContext } from './SubscriptionContext';
import { IMessageDispatcher } from '../dispatch/IMessageDispatcher';
import HashMap from '@ohos.util.HashMap';
import { Utils } from '../utils/Utils';
import { LogUtil } from '../../../../utils/LogUtil';

export class Subscription {
  //包含处理的上下文，处理消息的handle、分发消息的patch
  private referenceMap: HashMap<String, Object> | WeakMap<String, Object>;
  private context: SubscriptionContext; //上下文
  private dispatch: IMessageDispatcher; // 分发消息接口
  private subClassName: String;

  constructor(context: SubscriptionContext, dispatch: IMessageDispatcher, isStrong: boolean) {
    LogUtil.info(`Subscription created with isStrong: ${isStrong}`);
    this.context = context;
    this.dispatch = dispatch;
    if (isStrong) {
      this.referenceMap = new HashMap<String, Object>();
    } else {
      this.referenceMap = new WeakMap<String, Object>();
    }
  }

  public unsubscribe(existingListener: Object): boolean {
    let key = Utils.getClassName(existingListener);
    if (key.valueOf() != this.subClassName.valueOf()) {
      return false;
    }
    let isUnSub = false;
    try {
      if (this.referenceMap instanceof HashMap && this.referenceMap.hasKey(this.subClassName)) {
        let value = this.referenceMap.remove(this.subClassName);
        isUnSub = true;
        value = null;
      } else if (this.referenceMap instanceof WeakMap && this.referenceMap.has(this.subClassName)) {
        isUnSub = this.referenceMap.delete(this.subClassName);
      }
    } catch (e) {
      LogUtil.error(e);
    }
    return isUnSub;
  }

  subscribe(listener: Object) {
    let key = Utils.getClassName(listener);
    let strKey = new String(key);
    try {
      this.referenceMap.set(strKey, listener);
    } catch (e) {
      LogUtil.error(e);
    }
    this.subClassName = strKey;
  }

  publish(msg: Object) {
    let listener = null;
    try {
      if (this.referenceMap instanceof HashMap && this.referenceMap.hasKey(this.subClassName)) {
        listener = this.referenceMap.get(this.subClassName);
      } else if (this.referenceMap instanceof WeakMap && this.referenceMap.has(this.subClassName)) {
        listener = this.referenceMap.get(this.subClassName);
      }
      if (this.dispatch && this.enable() && listener) {
        this.dispatch.dispatch(msg, this.getMethodName(), listener);
      }
    } catch (e) {
      LogUtil.error(e);
    }
  }

  getPriority(): number {
    return this.context.getHandleParameters().getHandleParameter().priority;
  }

  getMethodName(): String {
    return this.context.getHandleParameters().getMethodName();
  }

  enable(): boolean {
    return this.context.getHandleParameters().getHandleParameter().enabled;
  }
}